<?php
class Testsuite extends Object
{
	public $batchRun = false;

	protected function AssertEqual($supplied, $expected, $label = null)
	{
    	$message = new NestedMessage($label);
		$message->isPassed = $error['is_passed'] = $this->AssertEqualHelper($supplied, $expected);
		$error['supplied'] = $supplied;
		$error['expected'] = $expected;
		$message->error[] = $error;
		NestedMessage::Add($message);
	}

    protected function AssertObjectEqual($supplied, $expected, $label = null)
    {
        $message = new NestedMessage($label);
        NestedMessage::Push($message);

        $message->isPassed = true;

        $reflect = new ReflectionObject($expected);
        $properties = $reflect->getProperties();

        foreach($properties as $prop)
        {
            $prop_reflect = new ReflectionProperty($expected, $prop->name);
            $sprop_reflect = new ReflectionProperty($supplied, $prop->name);

            $pname = $prop->name;
            $getter = 'get'.ucfirst($prop->name);
            $value = method_exists($expected, $getter) ? $expected->$getter() : ($prop_reflect->isPublic() ? $expected->$pname : null);
            $svalue =  method_exists($supplied, $getter) ? $supplied->$getter() : ($sprop_reflect->isPublic() ? $supplied->$pname : null);

            if (is_object($value))
            {
                $msg = $this->AssertObjectEqual($svalue, $value, $prop->name);
                $error['is_passed'] = $msg->isPassed;
            }
            else
            {
                $error['is_passed'] = $this->AssertEqualHelper($svalue, $value);
            }
            $message->isPassed &= $error['is_passed'];
            $error['supplied'] = $svalue;
            $error['expected'] = $value;
            $message->error[$prop->name] = $error;
        }

        NestedMessage::Pop();
        return $message;
    }

    protected function AssertArrayEqual($supplied, $expected, $label = null)
    {
    	$message = new NestedMessage($label);
		NestedMessage::Push($message);

		$message->isPassed = true;
        foreach ($expected as $key => $value)
		{
			$svalue = isset($supplied[$key]) ? $supplied[$key] : null;
			if (is_array($value))
			{
				$msg = $this->AssertArrayEqual($svalue, $value, $key);
				$error['is_passed'] = $msg->isPassed;
			}
			else
			{
				$error['is_passed'] = $this->AssertEqualHelper($svalue, $value);
			}
			$message->isPassed &= $error['is_passed'];
			$error['supplied'] = $svalue;
			$error['expected'] = $value;
			$message->error[$key] = $error;
		}
		NestedMessage::Pop();
		return $message;
    }

    protected function AssertArrayEqualStrictly($supplied, $expected, $label = null)
    {
        $message = new NestedMessage($label);
        NestedMessage::Push($message);

        $message->isPassed = count($supplied) == count($expected);
        foreach ($expected as $key => $value)
        {
            $svalue = isset($supplied[$key]) ? $supplied[$key] : null;
            if (is_array($value))
            {
                $msg = $this->AssertArrayEqualStrictly($svalue, $value, $key);
                $error['is_passed'] = $msg->isPassed;
            }
            else
            {
                $error['is_passed'] = $this->AssertEqualHelper($svalue, $value);
            }
            $message->isPassed &= $error['is_passed'];
            $error['supplied'] = $svalue;
            $error['expected'] = $value;
            $message->error[$key] = $error;
        }

        foreach ($supplied as $key => $value)
        {
            if (!isset($expected[$key]))
            {
                if (is_array($value))
                {
                    $evalue = array();
                    $msg = $this->AssertArrayEqualStrictly($value, $evalue, $key);
                    $error['is_passed'] = $msg->isPassed;
                }
                else
                {
                    $evalue = null;
                    $error['is_passed'] = $this->AssertEqualHelper($value, $evalue);
                }
                $message->isPassed &= $error['is_passed'];
                $error['supplied'] = $value;
                $error['expected'] = '[NOT EXPECTED]';
                $message->error[$key] = $error;
            }
        }

        NestedMessage::Pop();
        return $message;
    }

    private function AssertEqualHelper($supplied, $expected)
    {
		return $supplied == $expected;
    }

    protected function PushMessageHeader($header)
	{
		NestedMessage::Push(new TestHeaderMessage($header));
	}

	protected function PopMessageHeader()
	{
		NestedMessage::Pop();
	}

	protected function AddMessageInfo($content, $header)
	{
		NestedMessage::Add(new MessageInfo($content, $header));
	}

    protected function AssertException($supplied, $expected)
    {
        $this->AssertEqual(get_class($supplied), $expected);
    }
}
?>
